﻿using System;
using System.Globalization;
using System.IO;

namespace BizElements.BusinessLayer
{
    /// <summary>
    /// Provides common text processing functionalities.
    /// </summary>
    public static class TextUtil
    {
        #region TrimNullableString.

        /// <summary>
        /// Trims and parses nullable strings.
        /// </summary>
        /// <param name="s">String or <b>null</b> reference.</param>
        /// <returns>Trimmed string or <b>null</b> if empty string is provided or yielded.</returns>
        public static string TrimNullableString(string s)
        {
            if (string.IsNullOrEmpty(s))
                return null;

            s = s.Trim();
            return (s.Length > 0) ? s : null;
        }

        #endregion

        #region EnsureSuffix.

        /// <summary>
        /// Checks whether the text ends with the specified suffix. If not, it will be appended.
        /// </summary>
        /// <param name="text">Text to check. Nulls are converted to empty strings.</param>
        /// <param name="suffix">Suffix. Nullable.</param>
        /// <returns>A string which ends with the specified suffix.</returns>
        public static string EnsureSuffix(string text, string suffix)
        {
            if (text == null)
                text = "";

            if (!string.IsNullOrEmpty(suffix) && !text.EndsWith(suffix))
                text += suffix;

            return text;
        }

        #endregion

        #region ReplaceNewLine.

        /// <summary>
        /// Replaces new line and/or carriage return characters with the specified value.
        /// </summary>
        /// <param name="text">Text to correct. Nullable.</param>
        /// <param name="newLineReplacementValue">A string to replace all occurrences of <b>\r\n</b>, <b>\n\r</b>, <b>\n</b> and <b>\r</b> strings. Nullable.</param>
        /// <returns>A string without <b>\r\n</b>, <b>\n\r</b>, <b>\n</b> and <b>\r</b> strings.</returns>
        public static string ReplaceNewLine(string text, string newLineReplacementValue)
        {
            if (text == null)
                text = "";
            if (newLineReplacementValue == null)
                newLineReplacementValue = "";

            text = text.Replace("\r\n", newLineReplacementValue);
            text = text.Replace("\n\r", newLineReplacementValue);
            text = text.Replace("\n", newLineReplacementValue);
            text = text.Replace("\r", newLineReplacementValue);
            return text;
        }

        #endregion

        #region RemovePrefix.

        /// <summary>
        /// Checks whether the text starts with the specified prefix. If it does, it will be removed.
        /// </summary>
        /// <param name="text">Text to check. Nullable.</param>
        /// <param name="prefix">Prefix. Nullable.</param>
        /// <returns>A string from which the prefix has been removed. <b>null</b> if input text is <b>null</b>. Empty string if prefix is equal to input text.</returns>
        public static string RemovePrefix(string text, string prefix)
        {
            string output;
            if (string.IsNullOrEmpty(text))
                output = text;
            else if (string.IsNullOrEmpty(prefix))
                output = text;
            else if (text.StartsWith(prefix))
                output = text.Remove(0, prefix.Length);
            else
                output = text;

            return output;
        }

        /// <summary>
        /// Checks whether the text starts with the specified prefix. If it does, it will be removed.
        /// </summary>
        /// <param name="text">Text to check. Nullable.</param>
        /// <param name="prefix">Prefix. Nullable.</param>
        /// <param name="comparisonType">One of the <see cref="StringComparison"/> values that determines how this string and value are compared.</param>
        /// <returns>A string from which the prefix has been removed. <b>null</b> if input text is <b>null</b>. Empty string if prefix is equal to input text.</returns>
        public static string RemovePrefix(string text, string prefix, StringComparison comparisonType)
        {
            string output;
            if (string.IsNullOrEmpty(text))
                output = text;
            else if (string.IsNullOrEmpty(prefix))
                output = text;
            else if (text.StartsWith(prefix, comparisonType))
                output = text.Remove(0, prefix.Length);
            else
                output = text;

            return output;
        }

        /// <summary>
        /// Checks whether the text starts with the specified prefix. If it does, it will be removed.
        /// </summary>
        /// <param name="text">Text to check. Nullable.</param>
        /// <param name="prefix">Prefix. Nullable.</param>
        /// <param name="ignoreCase"><b>true</b> to ignore case when comparing this string and value; otherwise, <b>false</b>.</param>
        /// <param name="culture">Cultural information that determines how this string and value are compared. If culture is <b>null</b>, the current culture is used.</param>
        /// <returns>A string from which the prefix has been removed. <b>null</b> if input text is <b>null</b>. Empty string if prefix is equal to input text.</returns>
        public static string RemovePrefix(string text, string prefix, bool ignoreCase, CultureInfo culture)
        {
            string output;
            if (string.IsNullOrEmpty(text))
                output = text;
            else if (string.IsNullOrEmpty(prefix))
                output = text;
            else if (text.StartsWith(prefix, ignoreCase, culture))
                output = text.Remove(0, prefix.Length);
            else
                output = text;

            return output;
        }

        #endregion

        #region CountLines.

        /// <summary>Counts the number of lines in given text.</summary>
        /// <param name="text">Text to analyze.</param>
        /// <returns>Number of lines in the given text.</returns>
        public static int CountLines(string text)
        {
            int lineCount = 0;
            using (StringReader reader = new StringReader(text))
            {
                while (null != reader.ReadLine())
                    lineCount++;
            }

            return lineCount;
        }

        #endregion

        #region RemoveSuffix.

        /// <summary>Safely removes the specified suffix from the given text.</summary>
        /// <param name="text">Text to trim. If <b>null</b> nothing happens, ie. <b>null</b> is returned.</param>
        /// <param name="suffix">Suffix to remove. If <b>null</b> or <see cref="String.Empty"/> nothing happens, ie. original value is returned.</param>
        public static string RemoveSuffix(string text, string suffix)
        {
            string trimmedText;
            if ((text != null) && (suffix != null) && text.EndsWith(suffix))
            {
                int cutAt = text.Length - suffix.Length;
                trimmedText = text.Substring(0, cutAt);
            }
            else
            {
                trimmedText = text;
            }

            return trimmedText;
        }

        #endregion
    }
}